package com.liang.exam.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.github.pagehelper.PageInfo;
import com.liang.exam.entity.Exam;
import com.liang.exam.entity.ExamStudent;
import com.liang.exam.entity.Result;
import com.liang.exam.entity.Teacher;
import com.liang.exam.service.TeacherService;
import com.liang.exam.utils.Md5Util;
import com.liang.exam.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/teacher")
public class TeacherController {
    @Autowired
    private TeacherService teacherService;

    public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
    private static final Logger log = LoggerFactory.getLogger(TeacherController.class);

    /**
     * 创建一个新的考试
     *
     * @param exam 包含考试信息的对象
     * @return 返回创建考试的结果信息
     * @throws Exception 当创建考试过程中出现异常时抛出
     */
    @PostMapping("/createExam")
    public Result<String> createExam(@RequestBody Exam exam) {
        Map<String, Object> claims = ThreadLocalUtil.get();

        Result<String> validationResult = validateAndSetExamStatus(exam);
        if (validationResult.getCode() != 0) {
            return validationResult;
        }

        int id = (int) claims.get("id");
        exam.setTeacherId(id);
        System.out.println(exam);
        try {
            teacherService.createExam(exam);
            return Result.success("新建考试成功");
        } catch (Exception e) {
            log.error("Failed to create exam: {}", e);
            return Result.error("新建考试失败");
        }
    }

    @DeleteMapping("/deleteExam")
    public Result<String> deleteExam(@RequestParam("examId") Integer examId) {
        try {
            teacherService.deleteExam(examId);
            return Result.success("删除考试成功");
        } catch (Exception e) {
            log.error("Failed to delete exam: {}", e);
            return Result.error("删除考试失败");
        }
    }

    @DeleteMapping("/deleteStudent")
    public Result<String> deleteStudent(@RequestParam("studentId") Integer id) {
        try {
            teacherService.deleteStudent(id);
            return Result.success("删除考生成功");
        } catch (Exception e) {
            log.error("Failed to delete student: {}", e);
            return Result.error("删除考生失败");
        }
    }

    /**
     * 更新考试信息
     *
     * @param exam 包含考试信息的对象
     * @param file 要上传的文件，可选
     * @return 返回更新考试的结果信息
     * @throws Exception 当更新考试过程中出现异常时抛出
     */
    @PostMapping("/updateExam")
    public Result<String> updateExam(@RequestPart("exam") Exam exam, @RequestPart(value = "file", required = false) MultipartFile file) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        String teacherName = (String) claims.get("username");

        Result<String> validationResult = validateAndSetExamStatus(exam);
        if (validationResult.getCode() != 0) {
            return validationResult;
        }

        if (file != null && !file.isEmpty()) {
            try {
                String filePath = saveFile(file, exam.getExamName(), teacherName);
                exam.setFilePath(filePath);
            } catch (IOException e) {
                return Result.error("更新考试失败");
            }
        }
        try {
            teacherService.updateExam(exam);
            System.out.println(exam);
            return Result.success("更新考试成功");
        } catch (Exception e) {
            log.error("Failed to update exam: {}", e);
            return Result.error("更新考试失败");
        }
    }

    @GetMapping("/updateExamStatus")
    public Result updateExamStatus(@RequestParam("examId") Integer examId){
        teacherService.updateExamStatus(examId);
        System.out.println("更新考试状态成功");
        return Result.success();
    }



    /**
     * 保存上传的文件
     *
     * @param file 上传的文件
     * @return 保存文件的路径
     * @throws IOException 如果发生IO异常则抛出
     */
    public String saveFile(MultipartFile file, String examName, String teacherName) throws IOException {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        if (fileName == null || fileName.isEmpty()) {
            throw new IOException("文件名为空");
        }
        // 获取项目根目录路径
        String projectRoot = System.getProperty("user.dir") + "/exam" + "/src";
        // 设置目标路径：项目根目录下的 uploads/Papers 文件夹
        String uploadDir = projectRoot + "/uploads" + "/" + examName + "_" + teacherName + "/Papers";
        String submitDir = projectRoot + "/uploads" + "/" + examName + "_" + teacherName + "/Answer";
        Path uploadPath = Paths.get(uploadDir);
        Path submitPath = Paths.get(submitDir);
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath); // 确保目标目录存在
        }
        if (!Files.exists(submitPath)) {
            Files.createDirectories(submitPath); // 确保目标目录存在
        }
        // 生成文件路径
        Path filePath = uploadPath.resolve(fileName);
        // 保存文件到目标路径
        file.transferTo(filePath.toFile());
        return filePath.toString();
    }


    /**
     * 获取单场考试信息
     *
     * @param examId 考试ID
     * @return 返回考试信息对象
     * @throws RuntimeException 如果考试信息不存在，则抛出运行时异常
     */
    @GetMapping("/getExamInfoById")
    public Exam getExamInfo(Integer examId) {
        Exam exam = teacherService.getExamInfo(examId);
        if (exam == null) {
            throw new RuntimeException("考试信息不存在");
        }
        System.out.println(exam);
        return exam;
    }


    /**
     * 获取教师的所有考试信息
     *
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @return 包含考试信息的分页结果
     */
    @GetMapping("/getExamInfo")
    public Result<PageInfo<Exam>> allExam(Integer pageNum, Integer pageSize) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        int teacherId = (int) claims.get("id");
        PageInfo<Exam> pageInfo = teacherService.selectAll(pageNum, pageSize, teacherId);
        List<Exam> examList = pageInfo.getList();
        for (Exam item : examList) {
            String filePath = item.getFilePath();
            if (filePath!= null &&!filePath.isEmpty()) {
                try {
                    System.out.println(filePath);
                    byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
                    String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);
                    item.setFileBase64(base64Encoded);
                    String fileName = new File(filePath).getName();
                    item.setFileName(fileName);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 可以根据实际情况进行更合适的错误处理，比如记录日志、返回特定错误码的Result等
                }
            }
        }
        return Result.success(pageInfo);
    }

    @PostMapping("/searchExam")
    public Result<PageInfo<Exam>> searchExam(@RequestBody Exam exam,@RequestParam Integer pageNum,@RequestParam Integer pageSize) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        System.out.println(exam);
        int teacherId = (int) claims.get("id");
        exam.setTeacherId(teacherId);
        PageInfo<Exam> pageInfo = teacherService.searchExam(pageNum, pageSize, exam);
        List<Exam> examList = pageInfo.getList();
        for (Exam item : examList) {
            String filePath = item.getFilePath();
            if (filePath!= null &&!filePath.isEmpty()) {
                try {
                    System.out.println(filePath);
                    byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
                    String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);
                    item.setFileBase64(base64Encoded);
                    String fileName = new File(filePath).getName();
                    item.setFileName(fileName);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 可以根据实际情况进行更合适的错误处理，比如记录日志、返回特定错误码的Result等
                }
            }
        }
        return Result.success(pageInfo);
    }


    @GetMapping("/getExamStudentInfo")
    public Result<PageInfo<ExamStudent>> studentExam(Integer id, Integer pageNum, Integer pageSize) {
        PageInfo<ExamStudent> pageInfo = teacherService.selectExamStudent(pageNum, pageSize, id);
        return Result.success(pageInfo);
    }

    @PostMapping("/findStudentExam")
    public Result<PageInfo<ExamStudent>> findStudentExam(@RequestBody ExamStudent examStudent,@RequestParam Integer pageNum,@RequestParam Integer pageSize) {
        PageInfo<ExamStudent> pageInfo = teacherService.findStudentExam(examStudent, pageNum, pageSize);
        return Result.success(pageInfo);
    }


    @PostMapping("/addStudentExam")
    public Result<String> addStudentExam(@RequestBody ExamStudent examStudent) {
        try {
            System.out.println(examStudent);
            teacherService.addStudentExam(examStudent);
            return Result.success("添加考生成功");
        } catch (Exception e) {
            log.error("Failed to create exam: {}", e);
            return Result.error("添加考试失败");
        }
    }

    @PostMapping("/excelUpload")
    public Result<String> uploadStudentExcel(@RequestParam("file") MultipartFile file, @RequestParam("examId") String examId) {
        if (file.isEmpty()) {
            return Result.error("文件为空");
        }
        try {
            List<ExamStudent> studentList = new ArrayList<>();
            // 使用easyexcel读取Excel文件内容并转换为Student对象列表
            EasyExcel.read(file.getInputStream(), ExamStudent.class, new AnalysisEventListener<ExamStudent>() {
                @Override
                public void invoke(ExamStudent student, AnalysisContext analysisContext) {
                    studentList.add(student);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                    // 所有数据解析完成后的操作，这里可以做一些后续处理，比如保存数据到数据库等
                }
            }).sheet().doRead();

            // 调用Service层方法保存学生考试信息到数据库
            teacherService.addStudentExamList(studentList, examId);

            return Result.success("文件上传成功");
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error("文件上传失败");
        }

    }



    private Result<String> validateAndSetExamStatus(Exam exam) {

        LocalDateTime beginDateTime = LocalDateTime.parse(exam.getBeginTime(), formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(exam.getEndTime(), formatter);

        // 检查考试名称是否为空
        if (exam.getExamName() == null || exam.getExamName().trim().isEmpty()) {
            return Result.error("考试名称不能为空");
        }

        // 检查开始时间和结束时间是否为空
        if (exam.getBeginTime() == null || exam.getEndTime() == null) {
            return Result.error("开始时间和结束时间不能为空");
        }

        // 检查结束时间是否早于开始时间
        if (endDateTime.isBefore(beginDateTime)) {
            return Result.error("结束时间不能早于开始时间");
        }

        // 获取当前时间
        LocalDateTime currentTime = LocalDateTime.now();

        // 计算考试状态
        if (beginDateTime.isAfter(currentTime)) {
            exam.setStatus("未开始");
        } else if (endDateTime.isBefore(currentTime)) {
            exam.setStatus("已结束");
        } else {
            exam.setStatus("进行中");
        }

        // 返回成功结果
        return Result.success();
    }


    @PostMapping("/updatePassword")
    public Result<String> updatePassword(HttpServletRequest request) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        int teacherId = (int) claims.get("id");
        String oldPassword = request.getParameter("currentPassword");
        String newPassword = request.getParameter("newPassword");
        String newPassword2 = request.getParameter("confirmPassword");
        Teacher teacher = teacherService.findById(teacherId);
        if (!newPassword.equals(newPassword2)) {
            return Result.error("两次输入的新密码不一致");
        }
        if (oldPassword == null || newPassword == null) {
            return Result.error("请输入旧密码和新密码");
        } else if (!Md5Util.getMd5Encryption(oldPassword).equals(teacher.getPassword())) {
            return Result.error("旧密码错误");
        }

        String password= Md5Util.getMd5Encryption(newPassword);
        try {
            teacherService.updatePassword(password,teacherId);
            return Result.success("修改密码成功");
        }catch (Exception e) {
            return Result.error("修改密码失败");
        }
    }

    @GetMapping("/getTeacherInfo")
    public Result<Teacher> getTeacherInfo() {
        Map<String, Object> claims = ThreadLocalUtil.get();
        int teacherId = (int) claims.get("id");
        Teacher teacher = teacherService.findById(teacherId);
        return Result.success(teacher);
    }

}
